//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2022 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

import Foundation
import SotoCore

extension SSOOIDC {
    // MARK: Enums

    // MARK: Shapes

    public struct CreateTokenRequest: AWSEncodableShape {
        /// The unique identifier string for each client. This value should come from the persisted result of the RegisterClient API.
        public let clientId: String
        /// A secret string generated for the client. This value should come from the persisted result of the RegisterClient API.
        public let clientSecret: String
        /// The authorization code received from the authorization service. This parameter is required to perform an authorization grant request to get access to a token.
        public let code: String?
        /// Used only when calling this API for the device code grant type. This short-term code is used to identify this authentication attempt. This should come from an in-memory reference to the result of the StartDeviceAuthorization API.
        public let deviceCode: String?
        /// Supports grant types for the authorization code, refresh token, and device code request. For device code requests, specify the following value:
        ///   urn:ietf:params:oauth:grant-type:device_code
        ///  For information about how to obtain the device code, see the StartDeviceAuthorization topic.
        public let grantType: String
        /// The location of the application that will receive the authorization code. Users authorize the service to send the request to this location.
        public let redirectUri: String?
        /// Currently, refreshToken is not yet implemented and is not supported. For more information about the features and limitations of the current IAM Identity Center OIDC implementation, see Considerations for Using this Guide in the IAM Identity Center OIDC API Reference. The token used to obtain an access token in the event that the access token is invalid or expired.
        public let refreshToken: String?
        /// The list of scopes that is defined by the client. Upon authorization, this list is used to restrict permissions when granting an access token.
        public let scope: [String]?

        public init(clientId: String, clientSecret: String, code: String? = nil, deviceCode: String? = nil, grantType: String, redirectUri: String? = nil, refreshToken: String? = nil, scope: [String]? = nil) {
            self.clientId = clientId
            self.clientSecret = clientSecret
            self.code = code
            self.deviceCode = deviceCode
            self.grantType = grantType
            self.redirectUri = redirectUri
            self.refreshToken = refreshToken
            self.scope = scope
        }

        private enum CodingKeys: String, CodingKey {
            case clientId
            case clientSecret
            case code
            case deviceCode
            case grantType
            case redirectUri
            case refreshToken
            case scope
        }
    }

    public struct CreateTokenResponse: AWSDecodableShape {
        /// An opaque token to access IAM Identity Center resources assigned to a user.
        public let accessToken: String?
        /// Indicates the time in seconds when an access token will expire.
        public let expiresIn: Int?
        /// Currently, idToken is not yet implemented and is not supported. For more information about the features and limitations of the current IAM Identity Center OIDC implementation, see Considerations for Using this Guide in the IAM Identity Center OIDC API Reference. The identifier of the user that associated with the access token, if present.
        public let idToken: String?
        /// Currently, refreshToken is not yet implemented and is not supported. For more information about the features and limitations of the current IAM Identity Center OIDC implementation, see Considerations for Using this Guide in the IAM Identity Center OIDC API Reference. A token that, if present, can be used to refresh a previously issued access token that might have expired.
        public let refreshToken: String?
        /// Used to notify the client that the returned token is an access token. The supported type is BearerToken.
        public let tokenType: String?

        public init(accessToken: String? = nil, expiresIn: Int? = nil, idToken: String? = nil, refreshToken: String? = nil, tokenType: String? = nil) {
            self.accessToken = accessToken
            self.expiresIn = expiresIn
            self.idToken = idToken
            self.refreshToken = refreshToken
            self.tokenType = tokenType
        }

        private enum CodingKeys: String, CodingKey {
            case accessToken
            case expiresIn
            case idToken
            case refreshToken
            case tokenType
        }
    }

    public struct RegisterClientRequest: AWSEncodableShape {
        /// The friendly name of the client.
        public let clientName: String
        /// The type of client. The service supports only public as a client type. Anything other than public will be rejected by the service.
        public let clientType: String
        /// The list of scopes that are defined by the client. Upon authorization, this list is used to restrict permissions when granting an access token.
        public let scopes: [String]?

        public init(clientName: String, clientType: String, scopes: [String]? = nil) {
            self.clientName = clientName
            self.clientType = clientType
            self.scopes = scopes
        }

        private enum CodingKeys: String, CodingKey {
            case clientName
            case clientType
            case scopes
        }
    }

    public struct RegisterClientResponse: AWSDecodableShape {
        /// The endpoint where the client can request authorization.
        public let authorizationEndpoint: String?
        /// The unique identifier string for each client. This client uses this identifier to get authenticated by the service in subsequent calls.
        public let clientId: String?
        /// Indicates the time at which the clientId and clientSecret were issued.
        public let clientIdIssuedAt: Int64?
        /// A secret string generated for the client. The client will use this string to get authenticated by the service in subsequent calls.
        public let clientSecret: String?
        /// Indicates the time at which the clientId and clientSecret will become invalid.
        public let clientSecretExpiresAt: Int64?
        /// The endpoint where the client can get an access token.
        public let tokenEndpoint: String?

        public init(authorizationEndpoint: String? = nil, clientId: String? = nil, clientIdIssuedAt: Int64? = nil, clientSecret: String? = nil, clientSecretExpiresAt: Int64? = nil, tokenEndpoint: String? = nil) {
            self.authorizationEndpoint = authorizationEndpoint
            self.clientId = clientId
            self.clientIdIssuedAt = clientIdIssuedAt
            self.clientSecret = clientSecret
            self.clientSecretExpiresAt = clientSecretExpiresAt
            self.tokenEndpoint = tokenEndpoint
        }

        private enum CodingKeys: String, CodingKey {
            case authorizationEndpoint
            case clientId
            case clientIdIssuedAt
            case clientSecret
            case clientSecretExpiresAt
            case tokenEndpoint
        }
    }

    public struct StartDeviceAuthorizationRequest: AWSEncodableShape {
        /// The unique identifier string for the client that is registered with IAM Identity Center. This value should come from the persisted result of the RegisterClient API operation.
        public let clientId: String
        /// A secret string that is generated for the client. This value should come from the persisted result of the RegisterClient API operation.
        public let clientSecret: String
        /// The URL for the AWS access portal. For more information, see Using the AWS access portal in the IAM Identity Center User Guide.
        public let startUrl: String

        public init(clientId: String, clientSecret: String, startUrl: String) {
            self.clientId = clientId
            self.clientSecret = clientSecret
            self.startUrl = startUrl
        }

        private enum CodingKeys: String, CodingKey {
            case clientId
            case clientSecret
            case startUrl
        }
    }

    public struct StartDeviceAuthorizationResponse: AWSDecodableShape {
        /// The short-lived code that is used by the device when polling for a session token.
        public let deviceCode: String?
        /// Indicates the number of seconds in which the verification code will become invalid.
        public let expiresIn: Int?
        /// Indicates the number of seconds the client must wait between attempts when polling for a session.
        public let interval: Int?
        /// A one-time user verification code. This is needed to authorize an in-use device.
        public let userCode: String?
        /// The URI of the verification page that takes the userCode to authorize the device.
        public let verificationUri: String?
        /// An alternate URL that the client can use to automatically launch a browser. This process skips the manual step in which the user visits the verification page and enters their code.
        public let verificationUriComplete: String?

        public init(deviceCode: String? = nil, expiresIn: Int? = nil, interval: Int? = nil, userCode: String? = nil, verificationUri: String? = nil, verificationUriComplete: String? = nil) {
            self.deviceCode = deviceCode
            self.expiresIn = expiresIn
            self.interval = interval
            self.userCode = userCode
            self.verificationUri = verificationUri
            self.verificationUriComplete = verificationUriComplete
        }

        private enum CodingKeys: String, CodingKey {
            case deviceCode
            case expiresIn
            case interval
            case userCode
            case verificationUri
            case verificationUriComplete
        }
    }
}

// MARK: - Errors

/// Error enum for SSOOIDC
public struct SSOOIDCErrorType: AWSErrorType {
    enum Code: String {
        case accessDeniedException = "AccessDeniedException"
        case authorizationPendingException = "AuthorizationPendingException"
        case expiredTokenException = "ExpiredTokenException"
        case internalServerException = "InternalServerException"
        case invalidClientException = "InvalidClientException"
        case invalidClientMetadataException = "InvalidClientMetadataException"
        case invalidGrantException = "InvalidGrantException"
        case invalidRequestException = "InvalidRequestException"
        case invalidScopeException = "InvalidScopeException"
        case slowDownException = "SlowDownException"
        case unauthorizedClientException = "UnauthorizedClientException"
        case unsupportedGrantTypeException = "UnsupportedGrantTypeException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize SSOOIDC
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// You do not have sufficient access to perform this action.
    public static var accessDeniedException: Self { .init(.accessDeniedException) }
    /// Indicates that a request to authorize a client with an access user session token is pending.
    public static var authorizationPendingException: Self { .init(.authorizationPendingException) }
    /// Indicates that the token issued by the service is expired and is no longer valid.
    public static var expiredTokenException: Self { .init(.expiredTokenException) }
    /// Indicates that an error from the service occurred while trying to process a request.
    public static var internalServerException: Self { .init(.internalServerException) }
    /// Indicates that the clientId or clientSecret in the request is invalid. For example, this can occur when a client sends an incorrect clientId or an expired clientSecret.
    public static var invalidClientException: Self { .init(.invalidClientException) }
    /// Indicates that the client information sent in the request during registration is invalid.
    public static var invalidClientMetadataException: Self { .init(.invalidClientMetadataException) }
    /// Indicates that a request contains an invalid grant. This can occur if a client makes a CreateToken request with an invalid grant type.
    public static var invalidGrantException: Self { .init(.invalidGrantException) }
    /// Indicates that something is wrong with the input to the request. For example, a required parameter might be missing or out of range.
    public static var invalidRequestException: Self { .init(.invalidRequestException) }
    /// Indicates that the scope provided in the request is invalid.
    public static var invalidScopeException: Self { .init(.invalidScopeException) }
    /// Indicates that the client is making the request too frequently and is more than the service can handle.
    public static var slowDownException: Self { .init(.slowDownException) }
    /// Indicates that the client is not currently authorized to make the request. This can happen when a clientId is not issued for a public client.
    public static var unauthorizedClientException: Self { .init(.unauthorizedClientException) }
    /// Indicates that the grant type in the request is not supported by the service.
    public static var unsupportedGrantTypeException: Self { .init(.unsupportedGrantTypeException) }
}

extension SSOOIDCErrorType: Equatable {
    public static func == (lhs: SSOOIDCErrorType, rhs: SSOOIDCErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension SSOOIDCErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
